﻿using System;
using System.IO;
using UCore;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;
using System.Drawing.Printing;

namespace Twin {
    public partial class frmWrBloc : Form {

                
        public string GeneratedString { get; private set; }
        private string[] arg;
        //private string bits_opargs;

        private int INST_BITS = 0;
        private int INST_OP = 1;            //OP_WR_AREA, [cmfg], 1[area_name], [area_sn], k0=v0>k1=v1>kn=vn[kvs] 
        private int INST_CMFG = 2;
        private int INST_I_NAME = 3;        //iap:0x80
        private int INST_BLOC_SN = 4;
        //private int INST_I_MEMORY = 5;      //iap:2


        //Bloc
        private int BLOC_IAP = 0;
        private int BLOC_XME = 1;
        private string[] iBloc = { "80", "mass" };  //0x80

        
        //private int IAP = 0;
        //private int FRAM = 1;
        //private int MASS = 2;

        private int SIZE_OF_FATTR = 8;
        private int SIZE_OF_BYTE = 8;

        private int iChip;
        private XPort xport = new XPort();


        public frmWrBloc(XPort xport, string content, int iChip) {
            InitializeComponent();
            this.iChip = iChip;
            this.xport = xport;

            GeneratedString = content;

            arg = content.Split(',');

            //Chip选择
            //int index = UI.init_cmbChipSel(cmbChip, Ini.chip);

            //源测试文件选择
            int iTestFile = UI.init_cmbFileSel(cmbBloc, Ini.chip[iChip].test_file);

            //seg_size
            UI.init_cmbSegSize(cmbSegSize, Ini.chip[iChip]);


            //cmfg
            arg[INST_CMFG] = UI.init_cmbCmfg(cmbCmfg, arg[INST_CMFG]);
            //UI.init_cmbCom(cmbCom, Ini.defaultPort);


            // 读取INI文件并填充字典
            //Ini.ReadIniFile(Ini.iniDictionary, Ini.iniFilePath);
            arg[INST_BLOC_SN] = Ini.iniDictionary["Info"]["FileSn"];
            statusSnFile.Text = "sn_file: 0x" + arg[INST_BLOC_SN] + " ";
            //arg[INST_BLOC_SN] = (Twin.TConsole.SnFile++).ToString("x");

            //arg[INST_I_MEMORY] = Ini.chip_mem[Ini.M_IAP];
        }


        private void frmWrBloc_Load(object sender, EventArgs e) {
            //TopMost = true;
            FormBorderStyle = FormBorderStyle.FixedSingle; // 设置窗体边框样式为固定单线框
            MaximizeBox = false;   // 移除最大化按钮
            MinimizeBox = false;   // 禁止调整大小

            //显示芯片型号
            lblChip.Text += Ini.chip[iChip].name;

            TConsole.PositionFormAtTopRight(this);
        }


        private void listBox2_SelectedIndexChanged_1(object sender, EventArgs e) {

        }

        private void dgvEdit_CellContentClick(object sender, DataGridViewCellEventArgs e) {

        }

        private void cmbAreas_SelectedIndexChanged(object sender, EventArgs e) {
        }

        private void cmbCmfg_SelectedIndexChanged(object sender, EventArgs e) {
            arg[INST_CMFG] = cmbCmfg.SelectedItem.ToString();
            if (arg[INST_CMFG].Equals("空")) {
                arg[INST_CMFG] = "";
            }
        }


        private string getIapFile() {
            string iap_fname = Ini.dir_io_file + "\\" + cmbBloc.SelectedItem.ToString();
            return iap_fname;
        }


        private void generateIapTestFile(int i) {
            byte[] fileBytes = Array.Empty<byte>();
            long nPage = 0;

            int page_size = int.Parse(cmbSegSize.Text);   // 每页128字节

            // 生成单页数据（0x00-0x7F）
            byte[] pageBytes = new byte[page_size];
            for (int j = 0; j < page_size; j++) {
                pageBytes[j] = (byte)(j & 0xFF);
            }

            // 计算需要重复的页数
            nPage = Ini.chip[i].vol / page_size;

            // 使用内存流高效拼接二进制数据
            using (MemoryStream ms = new MemoryStream()) {
                for (int j = 0; j < nPage; j++) {
                    ms.Write(pageBytes, 0, pageBytes.Length);
                }
                fileBytes = ms.ToArray();
            }

            // mark_size决定的最大字节数
            //long limit = ((Ini.chip[i].mark_size - SIZE_OF_FATTR) * SIZE_OF_BYTE) * page_size;     
            long size = Math.Min(Ini.chip[i].vol, Ini.chip[i].limit);


            // 二进制方式写入文件，只写入前size个字节
            string fn = getIapFile();
            using (FileStream fs = new FileStream(fn, FileMode.Create)) {
                fs.Write(fileBytes, 0, (int)size);
            }

            MessageBox.Show($"文件生成:\r\n\"{fn}\"\r\nsize:{size}");
        }


        private string setFileSn() {
            string hexSn;

            // 读取INI文件并填充字典
            //Ini.ReadIniFile(Ini.iniDictionary, Ini.iniFilePath);
            hexSn = Ini.iniDictionary["Info"]["FileSn"];      //Ini文件中是十进制

            // 移除十六进制前缀（如果存在）并转换为整数
            string hexValue = hexSn.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
                              ? hexSn.Substring(2)
                              : hexSn;
            int sn = Convert.ToInt32(hexValue, 16) + 1;  // 按十六进制解析并加1
            string sHex = sn.ToString("X");  // 例如 0x22

            Ini.WriteKeyValue(Ini.path_Console_ini, "Info.FileSn", "0x" + sHex);
            statusSnFile.Text = "sn_file: 0x" + sHex + " ";

            return sHex;
        }


        private string ConvertBinaryToHexString(string filePath) {
            try {
                // 读取二进制文件
                byte[] fileBytes = File.ReadAllBytes(filePath);

                // 预分配字符串缓冲区（每个字节对应2个字符）
                StringBuilder hexBuilder = new StringBuilder(fileBytes.Length * 2);

                // 遍历每个字节转换
                foreach (byte b in fileBytes) {
                    // 使用X2格式确保两位十六进制表示
                    hexBuilder.Append(b.ToString("X2"));
                }

                return hexBuilder.ToString();
            } catch (Exception ex) {
                MessageBox.Show($"文件读取失败：{ex.Message}");
                return string.Empty;
            }
        }

        
        //BLOC读			 =OP_RD_BLOC, [cmfg], 0[i_bloc],[addr],[len]						|0003	//ack_args:"Name,FileSn"
        //BLOC写(单帧)    =OP_WR_BLOC, [cmfg], 1[i_bloc],[addr],[hex]						    |0003	//场景:1)delta-iap; 2)随机写mass(短)
        //BLOC写(多帧0)   =OP_WR_BLOC, [cmfg], 1[i_bloc],[bloc_sn],  		[seg][hex]			|0003	//场景:1)full-iap; 2)随机写mass(长)
        //BLOC写(多帧)    =OP_WR_BLOC, [cmfg], 1[i_bloc],[bloc_sn],  		[seg][hex]			|0003	//
        private void btnSend_Click(object sender, EventArgs e) {
            string wr_bloc = "";

            if (Ini.chip[iChip].description.Contains("iap")) {
                string fn = getIapFile();

                wr_bloc = ConvertBinaryToHexString(fn);


                //int page_size = int.Parse(cmbSegSize.Text);   // 每页128字节
                //long limit = ((Ini.chip[i].mark_size - SIZE_OF_FATTR) * SIZE_OF_BYTE) * page_size;

                //check iap.bin长度
                long nBytes = wr_bloc.Length / 2;
                if (nBytes > Ini.chip[iChip].limit) {
                    MessageBox.Show($"文件\"{fn}\"太长， exceed limit:{Ini.chip[iChip].limit}");
                    return;
                }
            }

                
            //int iPort = int.Parse(cmbCom.Text.Replace("com", "")) - 1;
            CInfo cInfo = new CInfo();

            Msg.setInfo_bits(ref cInfo, arg[INST_BITS]);

            cInfo.sbCascade = "0";                              //单帧
            if (chkWrAll.Checked) { cInfo.sbCascade = "1"; }     //多帧(即使只有1帧，也按多帧编码)

            cInfo.sSegSize = cmbSegSize.SelectedItem.ToString();

            arg[INST_I_NAME] = iBloc[BLOC_IAP];
            arg[INST_BLOC_SN] = setFileSn();


            string opargs = arg[INST_OP] + "," + arg[INST_CMFG] + "," + arg[INST_I_NAME] + "," + arg[INST_BLOC_SN];

            cInfo.sOpArgs = opargs;
            TConsole.sendAsProtocol(xport, ref cInfo, wr_bloc, "cobra");
        }


        private void btnGenerateTestFile_Click(object sender, EventArgs e) {
            //int iChip = cmbChip.SelectedIndex;
            //string fn = cmbBloc.SelectedItem.ToString();
            generateIapTestFile(iChip); // fn);
        }

        
        private void cmbBloc_SelectedIndexChanged(object sender, EventArgs e) {
            //iap_fname = Ini.dir_io_file + "\\" + cmbBloc.SelectedItem.ToString();
        }


        private void cmbSegSize_SelectedIndexChanged(object sender, EventArgs e) {
            int page_size = int.Parse(cmbSegSize.Text);   // 每页128字节
            Ini.chip[iChip].limit = ((Ini.chip[iChip].mark_size - SIZE_OF_FATTR) * SIZE_OF_BYTE) * page_size;
        }
    }

}

